import os
import threading
import time
import tkinter as tk
from concurrent.futures import ProcessPoolExecutor
from tkinter import messagebox

import pandas as pd
from openpyxl import Workbook

##############################
from src import logPro

# 全局变量
CPUS = os.cpu_count()  # 获取CPU核心数量
max_workers = int(CPUS / 2)  # 定义工作进程数量


def message_show(type, content):
    """
    弹窗提示
    :param type: types = ['info', 'warning', 'error']
    :param content: 提示信息，类型为字符串
    """
    root = tk.Tk()
    root.withdraw()
    if type == 'info':
        messagebox.showinfo('提示', content)
    elif type == 'warning':
        messagebox.showwarning('警告', content)
    elif type == 'error':
        messagebox.showerror('错误', content)
    else:
        return
    root.destroy()


def transfer_file(asc_file_dir, asc_file_name, xlsx_file_dir):
    """
    单个文件转换:将asc格式的文件转换为excel类型的文件
    :param asc_file_dir:  asc文件所在路径
    :param asc_file_name: asc文件名
    :param xlsx_file_dir: excel文件保存路径
    """
    asc_file_path = os.path.join(asc_file_dir, asc_file_name)  # asc文件完整路径
    excel_file_name = os.path.splitext(asc_file_name)[0] + ".xlsx"  # excel文件名
    excel_file_path = os.path.join(xlsx_file_dir, excel_file_name)  # excel文件完整路径

    if not os.path.exists(asc_file_path):
        logPro.produce_logs("error", f"文件 {asc_file_name} 不存在")
        return

    start_time = time.time()  # 开始计时
    try:
        # 读取ASCII文件
        with open(asc_file_path, mode="r", encoding="utf-8") as f:
            lines = f.readlines()  # 读取所有行
        # 创建Excel工作簿和工作表，并直接保存
        wb = Workbook()
        ws = wb.active
        for line in lines:
            ws.append([line.strip()])  # [line.strip()]去除空白字符
        wb.save(excel_file_path)  # 保存excel文件
        end_time = time.time()  # 结束计时
        spend_time = int((end_time - start_time) * 1000)
        logPro.produce_logs("info", f"文件 {asc_file_name} 成功转换为 {excel_file_name}，耗时 {spend_time} ms")
    except Exception as e:
        end_time = time.time()  # 结束计时
        spend_time = int((end_time - start_time) * 1000)
        logPro.produce_logs("error", f"转换文件 {asc_file_name} 时出错: {e}，耗时 {spend_time} ms")


def transfer_files(asc_file_dir, xlsx_file_dir):
    """
    多个文件转换:将asc格式的文件转换为excel类型的文件
    :param asc_file_dir:  asc文件所在路径
    :param xlsx_file_dir: excel文件保存路径
    """
    # 检查上传目录是否存在文件
    asc_files = [f for f in os.listdir(asc_file_dir) if
                 os.path.isfile(os.path.join(asc_file_dir, f)) and f.endswith('.asc')]
    if not asc_files:  # 如果没有文件则记录日志同时弹窗提示，并切断函数运行
        logPro.produce_logs("info", f"{asc_file_dir}内没有需要转换的文件")
        message_show("info", "没有需要转换的文件")
        return
    total_files = len(asc_files)  # 待转换文件总数
    logPro.produce_logs("info", f"待转换 {total_files} 个文件")

    # 定义多进程任务，便于用多线程来管理它
    def multi_process():
        transfered_files = 0  # 已经转换文件数
        multi_start_time = time.time()  # 开始计时
        # 创建多进程任务，工作进程数为CPU核心数的1/2
        with ProcessPoolExecutor(max_workers=max_workers) as executor:
            futures = []  # 创建任务列表
            for asc_file_name in asc_files:
                futures.append(executor.submit(transfer_file, asc_file_dir, asc_file_name, xlsx_file_dir))
            for future in futures:
                try:
                    future.result()  # 等待所有任务完成并捕获异常
                    transfered_files += 1
                except Exception as e:
                    logPro.produce_logs("error", f"处理文件 {asc_file_name} 时出错: {e}")
        multi_end_time = time.time()  # 结束计时
        total_spend_time = int((multi_end_time - multi_start_time) * 1000)
        logPro.produce_logs("info", f"转换完成，共转换 {transfered_files} 个文件，总耗时 {total_spend_time} ms")
        message_show("info", f"共转换 {transfered_files} 个文件，总耗时 {total_spend_time} ms")

    multi_process_thread = threading.Thread(target=multi_process, daemon=True)
    multi_process_thread.start()


def process_file(files_dir, file_name):
    """
    单个文件处理: 对transfer_file转换完成后的初始文件继续加工
    :param files_dir:  excel文件所在路径
    :param file_name:  excel文件名
    """
    file_path = os.path.join(files_dir, file_name)
    start_time = time.time()  # 单个文件处理开始时间
    try:
        # 读取Excel文件
        df = pd.read_excel(file_path, engine="openpyxl", header=None)
        # 删除前三行和最后一行
        df = df.iloc[3:-1]
        # 将第一列按空格分列
        df = df.iloc[:, 0].str.split(" ", expand=True)
        # 设置所有数据类型为文本类型
        df = df.astype(str)
        # 添加标题行
        columns = ["时间", "通道", "ID", "方向", "类型", "长度", "byte0", "byte1", "byte2", "byte3", "byte4", "byte5",
                   "byte6", "byte7"]
        df.columns = columns
        # 保存处理后的Excel文件
        processed_file_path = os.path.join(files_dir, f"processed_{file_name}")
        df.to_excel(processed_file_path, index=False, engine="openpyxl")
        end_time = time.time()  # 单个文件处理结束时间
        spend_time = int((end_time - start_time) * 1000)
        logPro.produce_logs("info", f"文件 {file_name} 处理完成，耗时 {spend_time} ms")
        return True
    except Exception as e:
        end_time = time.time()  # 单个文件处理结束时间
        spend_time = int((end_time - start_time) * 1000)
        logPro.produce_logs("error", f"处理文件 {file_name} 时出错: {e}，耗时 {spend_time} ms")
        return False


def process_files(files_dir):
    """
    处理多个excel表格
    :param files_dir:  文件所在路径
    """
    # 检查临时目录是否存在文件
    files = [f for f in os.listdir(files_dir) if f.endswith(".xlsx") and not f.startswith("processed_")]
    if not files:
        logPro.produce_logs("info", f"{files_dir}内没有需要处理的文件")
        message_show("info", "没有需要处理的文件")
        return

    total_files = len(files)  # 待处理文件总数
    logPro.produce_logs("info", f"待处理 {total_files} 个文件")

    # 定义多进程任务，便于用多线程来管理它
    def multi_process():
        processed_files = 0  # 已经处理的文件数
        multi_start_time = time.time()  # 开始计时
        # 创建多进程任务，工作进程数为CPU核心数的1/2
        with ProcessPoolExecutor(max_workers=max_workers) as executor:
            futures = []  # 创建任务列表
            for excel_file_name in files:
                futures.append(executor.submit(process_file, files_dir, excel_file_name))
            for future in futures:
                try:
                    future.result()  # 等待所有任务完成并捕获异常
                    processed_files += 1
                except Exception as e:
                    logPro.produce_logs("error", f"处理文件 {excel_file_name} 时出错: {e}")
        multi_end_time = time.time()  # 结束计时
        total_spend_time = int((multi_end_time - multi_start_time) * 1000)
        logPro.produce_logs("info", f"处理完成，共处理 {processed_files} 个文件，总耗时 {total_spend_time} ms")
        message_show("info", f"共处理 {processed_files} 个文件，总耗时 {total_spend_time} ms")

    multi_process_thread = threading.Thread(target=multi_process, daemon=True)
    multi_process_thread.start()
